package com.geekhole.demo.email.application;

import com.geekhole.demo.email.domain.CreateEmailContext;
import com.geekhole.demo.email.domain.Email;
import com.geekhole.demo.email.domain.ModifyEmailContext;
import com.geekhole.demo.email.repository.EmailRepository;
import com.geekhole.demo.user.application.UserApplication;
import com.geekhole.demo.user.domain.CreateAndEnableUserContext;
import com.geekhole.demo.user.domain.ModifyUserNameContext;
import com.geekhole.demo.user.domain.User;
import com.geekhole.demo.user.domain.UserNotFoundException;
import com.geekhole.demo.user.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class EmailApplication {
    private static final Logger LOGGER = LoggerFactory.getLogger(EmailApplication.class);

    @Autowired
    private EmailRepository emailRepository;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Transactional(readOnly = false)
    public void createEmail(CreateEmailContext context){
        try {
            // 1. 生成 聚合根
            Email email = Email.create(context.getUserId(), context.getEmail());

            // 2. 执行业务访问
            email.init();

            // 3. 保存聚合根
            this.emailRepository.save(email);

            // 4. 发布领域事件
            email.foreachEvent(this.eventPublisher::publishEvent);

            // 5. 清理领域事件
            email.clearEvents();

            LOGGER.info("success to handle createEmail and sync {} to DB", email);
        }catch (Exception e){
            LOGGER.error("failed to handle createEmail", e);
            if (e instanceof RuntimeException){
                throw (RuntimeException) e;
            }
            throw new RuntimeException(e);
        }

    }


    @Transactional(readOnly = false)
    public void modifyEmail(ModifyEmailContext context){
        try {

            // 1. 加载聚合根
            Email email = this.emailRepository.getByUserId(context.getUserId());

            // 2. 验证聚合根
            if (email == null){
                throw new UserNotFoundException(context.getUserId());
            }

            // 3. 调用聚合根方法
            email.modifyEmail(context.getEmail());

            // 4. 保存对象
            this.emailRepository.save(email);

            // 5. 发布领域事件
            email.foreachEvent(this.eventPublisher::publishEvent);

            // 6. 清理领域事件
            email.clearEvents();

            LOGGER.info("success to handle modifyEmail and sync {} to DB", email);
        }catch (Exception e){
            LOGGER.error("failed to handle modifyEmail", e);
            if (e instanceof RuntimeException){
                throw (RuntimeException) e;
            }
            throw new RuntimeException(e);
        }

    }

}
